import { Component } from 'cc';
import { stateManager, isState, watch } from '../state/state';
import { get, parsePath, shallowSet } from '../state/utils';

type WatchState = {
    peek(): any
}

/**
@property({
    type: CCBoolean,
    tooltip: "开启模板模式，使用模板后支持多路径监听\n如: {{0}}:{{1}}"
})

@property({
    type: CCString,
    tooltip: "要监听的单个路径",
    visible: function() {
        return !this.useTemplate
    }
})

@property({
    type: CCString,
    tooltip: "要监听的多个路径",
    visible: function() {
        return this.useTemplate
    }
})
*/

export class VMBase extends Component {
    useTemplate = false;

    watchPath = '';

    watchPathArr: string[] = [];

    /**
     * 是否可用的
     */
    private enable = false;

    #parentState: WatchState | null = null;

    private disposeWatch: () => void;

    /**
     * 子类重写onLoad时，一定要最先调用super.onLoad()
     */
    protected onLoad(): void {
        this.enable = this.isWatchPathValid();
        if (!this.enable) {
            return;
        }
    }

    /**
     * 向上查找最近的支持状态的节点，包含自身，最多找10层
     */
    private findNearestParentState(): WatchState | null {
        let count = 0;
        let target = this.node;
        while (target && count < 10) {
            const comp = target.components.find((_comp: any) => {
                const state = _comp.state;
                return isState(state);
            });

            if (comp) {
                return (comp as any).state;
            }
            target = target.parent;
            count++;
        }

        return null;
    }

    private isWatchPathValid() {
        if (this.useTemplate) {
            return this.watchPathArr.some((p) => !!p && !!p.trim());
        }
        return !!this.watchPath && !!this.watchPath.trim();
    }

    protected onEnable(): void {
        if (!this.enable) {
            return;
        }

        const pstate = this.getParentStateIfNeed();

        if (this.useTemplate) {
            this.disposeWatch = watch(this.watchPathArr, this.onValueChanged, pstate, this);
        } else {
            this.disposeWatch = watch(this.watchPath, this.onValueChanged, pstate, this);
        }
        this.onValueInit();
    }

    protected onDisable(): void {
        if (this.disposeWatch) {
            this.disposeWatch();
        }
    }

    private getParentStateIfNeed(): WatchState | null {
        if (this.#parentState) {
            return this.#parentState;
        }

        let need = false;
        if (this.useTemplate) {
            need = this.watchPathArr.some(p => !!p && p.startsWith('*.'));
        } else {
            need = !!this.watchPath && this.watchPath.startsWith('*.');
        }

        if (need) {
            const _state = this.findNearestParentState();
            if (_state) {
                this.#parentState = _state;
            } else {
                console.warn("@c[VMBase] 没有找到可绑定的状态，请检查是否存在父级的状态组件", 'color: red;');
            }
        }
        return this.#parentState;
    }

    private getState(path: string): WatchState | null {
        const pi = parsePath(path);
        if (pi.stateId === '*') {
            if (!this.#parentState) {
                this.#parentState = this.findNearestParentState();
            }
            return this.#parentState;
        }
        return stateManager.getState(pi.stateId);
    }

    getValue(path: string, defaultValue: any = undefined) {
        const state = this.getState(path);
        if (state) {
            const subpath = path.split('.').slice(1).join('.');
            return get(state.peek(), subpath, defaultValue);
        }
        return defaultValue;
    }

    setValue(path: string, value: any) {
        const state = this.getState(path);
        if (state) {
            const subpath = path.split('.').slice(1).join('.');
            shallowSet(state, subpath, value);
        }
    }

    onValueInit() {}

    onValueChanged(current: any | any[], prev: any | any[]) {}
}
